package com.googlecode.simplexer.io.implementation;

import java.io.*;
import static com.googlecode.ptrace.Ptrace.*;
import com.googlecode.simplexer.exception.UnexpectedEndOfFileException;
import com.googlecode.simplexer.io.*;

/**
 * A character sequence in an ASCII text file.
 * 
 * @author Sam Huang
 */
public class FileCharInputSequence implements CharInputSequence {

	private int column = 0;

	private int ln = 0;

	private String line;

	protected String fileName;

	private FileReader reader = null;

	private BufferedReader breader = null;

	public FileCharInputSequence() {

	}

	public FileCharInputSequence(File file) throws Exception {
		init(file);
	}

	public FileCharInputSequence(File file, int startAtLine) throws Exception {
		this(file);
		jumpToLine(startAtLine);
	}

	public FileCharInputSequence(String fileName) {
		File file = new File(fileName);
		init(file);
	}

	public FileCharInputSequence(String file, int startAtLine) throws Exception {
		this(file);
		jumpToLine(startAtLine);
	}

	public FileCharInputSequence(String file, String startAtColumn) throws Exception {
		this(file);
		jumpToColumn(Integer.valueOf(startAtColumn));
	}

	public void jumpToColumn(int startAtColumn) {
		column = startAtColumn;
	}

	public void backward(int length) {
		column -= length;
	}

	public void close() {
		try {
			if (breader != null) {
				breader.close();
			}
			if (reader != null) {
				reader.close();
			}
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	public String forward(int length) {
		ptrace(line);
		ptrace(column);
		String forward = line.substring(column, column + length);
		column += length;
		return forward;
	}

	public String forwardUntil(char chr) {
		char chrr;
		StringBuffer buffer = new StringBuffer();

		do {
			chrr = nextchr();
			buffer.append(chrr);
		} while (chrr != chr);
		return buffer.toString();
	}

	public int getColumn() {
		return column;
	}

	public String getLine() {
		return line;
	}

	public int getLineNumber() {
		return ln;
	}

	public String getName() {
		return fileName;
	}

	public void init(File file) {
		try {
			if (reader != null) {
				reader.close();
			}
			if (breader != null) {
				breader.close();
			}

			this.fileName = file.getName();
			reader = new FileReader(file);
			breader = new BufferedReader(reader);
			nextLine();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	public void jumpToLine(int linesToJump) {
		try {
			for (int i = 1; i < linesToJump - 1; i++) {
				ln++;
				breader.readLine();
			}
			this.line = breader.readLine();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	public char nextchr() {
		// ptrace("column: " + column);
		// ptrace("length: " + line.length());

		if (column == line.length()) {
			nextLine();
		}
		return line.charAt(column++);
	}

	public void nextLine() {
		try {
			column = 0;
			do {
				ln++;
				line = breader.readLine();
				if (line == null) {
					breader.close();
					throw new UnexpectedEndOfFileException(fileName);
				}
			} while (line.length() == 0);
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
	}

}
